package utilities;

import java.util.LinkedList;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.Query;

/**
 * Classe di utilità per costruire una query jpql
 * @author Ale
 */
public class QueryBuilder{
    int whereClauses = 0;
    List<Object> queryParams = new LinkedList<Object>();
    String queryStr;
    EntityManager em;

    /**
     * Costruttore
     * @param from entity in cui cercare
     * @param em entity manager
     */
    public QueryBuilder (String from, EntityManager em){
        queryStr = "SELECT x FROM "+from+" x ";
        this.em = em;
    }

    /**
     * Aggiunge una clausola di uguaglianza: where field = obj
     * @param field campo della entity
     * @param obj oggetto con cui confrontare il campo
     */
    public void addWhereEqClause(String field, Object obj){
        if (whereClauses == 0) queryStr += " WHERE ";
        else queryStr += " AND ";
        whereClauses++;


        queryStr += "lower(x."+field+") LIKE lower(?"+whereClauses+")";
        queryParams.add(obj);                  
    }
    
    /**
     * Aggiunge una clausola di uguaglianza per numeri: where field = obj
     * @param field campo della entity
     * @param obj oggetto con cui confrontare il campo
     */
    public void addWhereEqNumClause(String field, Object obj){
        if (whereClauses == 0) queryStr += " WHERE ";
        else queryStr += " AND ";
        whereClauses++;


        queryStr += "x."+field+" = ?"+whereClauses+" ";
        queryParams.add(obj);                  
    }

    /**
     * Aggiunge una clausola di confronto: where field >= obj
     * @param field campo della entity
     * @param obj oggetto con cui confrontare il campo
     */
    public void addWhereLessEqClause(String field, Object obj) {
        if (whereClauses == 0) queryStr += " WHERE ";
        else queryStr += " AND ";
        whereClauses++;


        queryStr += "x."+field+" >= ?"+whereClauses;
        queryParams.add(obj);
    }

    /**
     * Aggiunge una clausola di confronto: where field <= obj
     * @param field campo della entity
     * @param obj oggetto con cui confrontare il campo
     */
    public void addWhereMoreEqClause(String field, Object obj) {
        if (whereClauses == 0) queryStr += " WHERE ";
        else queryStr += " AND ";
        whereClauses++;


        queryStr += "x."+field+" <= ?"+whereClauses;
        queryParams.add(obj);
    }
    
    /**
     * Aggiunge una clausola di confronto: where field > obj
     * @param field campo della entity
     * @param obj oggetto con cui confrontare il campo
     */
    public void addWhereLessClause(String field, Object obj) {
        if (whereClauses == 0) queryStr += " WHERE ";
        else queryStr += " AND ";
        whereClauses++;


        queryStr += "x."+field+" > ?"+whereClauses;
        queryParams.add(obj);
    }

    /**
     * Aggiunge una clausola di confronto: where field < obj
     * @param field campo della entity
     * @param obj oggetto con cui confrontare il campo
     */
    public void addWhereMoreClause(String field, Object obj) {
        if (whereClauses == 0) queryStr += " WHERE ";
        else queryStr += " AND ";
        whereClauses++;


        queryStr += "x."+field+" < ?"+whereClauses;
        queryParams.add(obj);
    }

    /**
     * Restituisce l'oggetto query corrispindente alla query creata
     * @return l'oggetto query corrispindente alla query creata
     */
    public Query getQueryObject(){
        Query q = em.createQuery(queryStr);
        for (int i=0; i<queryParams.size(); i++){
            q.setParameter(i+1, queryParams.get(i));
        }
        return q;
    }

    /**
     * Stampa la query creata in jpql
     */
    public void printQuery() {
        System.out.println(queryStr);
    }

    /**
     * Aggiunge una clausola di order by
     * @param field campo in base al quale ordinare il risultato
     */
    public void addOrderBy(String field) {
        queryStr += " ORDER BY x."+field;
    }

}
